import queue
from concurrent.futures import ThreadPoolExecutor
from datetime import datetime, timedelta

from flask import Blueprint, request

from business import business_video_creater_v1, business_video_creater_v2
from service import service_playbook
from common.json_response import JsonResponse
from model.models import db, TSysNovelChapter, TSysVideo
from configs import configs_service
from decimal import Decimal

CREATE_STATUS_UNREADY=0
CREATE_STATUS_CREATING=1
CREATE_STATUS_SUCCESS=2
CREATE_STATUS_ERROR=3

app_video_creator = Blueprint("app_video_creator", __name__)

video_temp_path = "../video_temp"

threadPool = ThreadPoolExecutor(max_workers=16, thread_name_prefix="create_img_")
video_create_q = queue.Queue()

@app_video_creator.route('/video/create', methods=["POST"])
def acquire_vedio_create_task():
    """创建视频剧本
                    ---
                    parameters:
                      - name: data
                        in: body
                        type: object
                        schema:
                          type: object
                          properties:
                            chapter_id:
                              type: int
                              example: 1
                            task_id:
                              type: string
                              example: ‘uuid-87656’
                            user_id:
                              type: int
                              example: 1
                            service_version:
                              type: int
                              example: 1
                        required: true
                        description: 创建视频剧本所需参数
                    responses:
                      200:
                        description: 返回创建视频剧本成功
                        examples:
                            {
                               "code": 0,
                               "data": null,
                               "msg": "success"
                            }
            """
    chapter_id = request.json.get('chapter_id')
    task_id = request.json.get('task_id')
    user_id = request.json.get('user_id')
    service_version = request.json.get('service_version')
    token_balance = request.json.get('token_balance')
    total_usage_tokens = Decimal(request.json.get('total_usage_tokens'))

    if service_version is None:
        service_version = 1

    # #30分内，如果有正在创建的视频，则拒绝服务
    #todo: 存disc
    create_video_timeout_time = datetime.now() + timedelta(minutes=-60)
    create_task_start_video_timeout_time = datetime.now() + timedelta(minutes=-30)

    if not video_token_balance_check(token_balance=token_balance, total_usage_tokens=total_usage_tokens, chapter_id=chapter_id, service_version=service_version):
        return JsonResponse.error(msg="您没足够的TOKEN来生成视频, 请充值！")

    # tsVideo = TSysVideo.query.filter(TSysVideo.chapter_id == chapter_id, (TSysVideo.create_stauts == 1) | (TSysVideo.create_stauts == 0), TSysVideo.create_task_start_time >= create_video_timeout_time).first()
    tsVideo = TSysVideo.query.filter(TSysVideo.chapter_id == chapter_id, (TSysVideo.create_stauts == 1) | (TSysVideo.create_stauts == 0)).order_by(TSysVideo.create_time.desc()).first()
    if tsVideo is not None :
        if tsVideo.create_task_start_time is not None and tsVideo.create_task_start_time != '':
            #还在任务过期时间内
            if tsVideo.create_task_start_time >= create_task_start_video_timeout_time:
                return JsonResponse.error(msg="相同章节视频已经在生成中，请耐心等待！")
        else:
            if tsVideo.create_time >= create_video_timeout_time:
                return JsonResponse.error(msg="相同章节视频正在等待生成中，请耐心等待！")

    novelChapter = TSysNovelChapter.query.filter_by(id=chapter_id).first()
    if novelChapter is None:
        return JsonResponse.error(msg="生成视频异常，无法找到对应小说！")

    novel_id = novelChapter.novel_id
    tsVideo = TSysVideo(
        user_id=user_id,
        novel_id=novel_id,
        chapter_id=chapter_id,
        task_id=task_id,
        name=novelChapter.title,
        create_progress=0,
        create_time=datetime.now()
    )
    db.session.add(tsVideo)
    db.session.flush()
    video_id = tsVideo.id
    db.session.commit()

    if chapter_id is None:
        change_video_create_status(video_id=video_id, status=CREATE_STATUS_ERROR, create_error_code='E0006')
        return JsonResponse.error(msg=str("创建视频失败,参数错误"))
    try:
        video_create_task_msg = {"chapter_id": chapter_id, "task_id":task_id, "video_id": video_id, "service_version":service_version}
        video_create_q.put(video_create_task_msg)
    except Exception as e:
        change_video_create_status(video_id=video_id, status=CREATE_STATUS_ERROR, create_error_code='E0005')

    return JsonResponse.success(msg=str("创建视频任务已经提交成功"), data={"task_id":task_id, "video_id": video_id})


@app_video_creator.route('/video/character/appearance/refresh', methods=["POST"])
def refresh_character_appearance():
    """创建视频剧本
                    ---
                    parameters:
                      - name: data
                        in: body
                        type: object
                        schema:
                          type: object
                          properties:
                            novel_id:
                              type: int
                              example: 1
                        required: true
                        description: 创建人物样貌所需参数
                    responses:
                      200:
                        description: 返回人物样貌本成功
                        examples:
                            {
                               "code": 0,
                               "data": null,
                               "msg": "success"
                            }
            """
    novel_id = request.json.get('novel_id')
    if novel_id is None:
        return JsonResponse.error(msg=str("创建人物样貌失败"), data=None)

    create_result = service_playbook.character_appearance_extraction(novel_id=novel_id)
    if create_result is None:
        return JsonResponse.error(msg=str("创建人物样貌失败"), data=None)
    if create_result.get("success") == False:
        return JsonResponse.error(msg=str("创建人物样貌失败"), data=None)


    return JsonResponse.success(msg=str("创建人物样貌成功"), data=None)


@app_video_creator.route('/video/create/status', methods=["POST"])
def vedio_create_status():
    """异步生成视频状态查询
        ---
        parameters:
          - name: data
            in: body
            type: object
            schema:
              type: object
              properties:
                video_id:
                  type: int
                  example: 1
            required: true
            description: 创建视频剧本所需参数
        responses:
          200:
            description: 返回异步生成小说章节大纲状态查询结果
            examples:
                {
                   "code": 0,
                   "data": null,
                   "msg": "success"
                }
    """
    video_id = request.json.get('video_id')
    if video_id is None:
        return JsonResponse.error(msg=str("创建视频失败,参数错误"))

    tsVideo = TSysVideo.query.filter_by(id=video_id).first()
    if tsVideo is None:
        return JsonResponse.error(msg=str("创建视频失败,视频为空"))

    create_progress = tsVideo.create_progress
    return JsonResponse.success(data={"create_progress": create_progress})

def create_video():
    msg = video_create_q.get()
    if msg is None:
        # TODO:logo
        print("msg 为空")
        return

    chapter_id = msg.get('chapter_id')
    task_id = msg.get('task_id')
    video_id = msg.get('video_id')
    service_version = msg.get('service_version')
    if service_version is None:
        service_version = 1

    print(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  任务id：" + str(task_id) + " 开始执行  >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>")
    if service_version == 1:
        business_video_creater_v1.create_video(chapter_id=chapter_id, task_id=task_id, video_id=video_id)
    elif service_version == 2:
        business_video_creater_v2.create_video(chapter_id=chapter_id, task_id=task_id, video_id=video_id)
    video_create_q.task_done()
    print("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<  任务id：" + str(task_id) + " 执行结束!  <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<")


def change_video_create_status(video_id,status,create_error_code):
    if video_id is None:
        return False
    video = TSysVideo.query.get(video_id)
    if video is None:
        return False
    video.create_stauts = status
    video.create_error_code = create_error_code
    db.session.commit()
    return True

def video_token_balance_check(token_balance,total_usage_tokens, chapter_id, service_version):
    current_token_usage = None
    if service_version == 1:
        current_token_usage = current_video_create_token_usage_v1(chapter_id=chapter_id)
    elif service_version == 2:
        current_token_usage = current_video_create_token_usage_v2(chapter_id=chapter_id)

    if current_token_usage is None:
        return False

    if token_balance < current_token_usage:
        return False
    return True

def current_video_create_token_usage_v1(chapter_id):
    token_video_len_proportion = configs_service.get_config('token_video_len_proportion')  # 字/秒
    novelChapter = TSysNovelChapter.query.filter_by(id=chapter_id).first()
    if novelChapter is None or novelChapter.content is None or len(novelChapter.content) <= 0:
        return 0
    return round(round(len(novelChapter.content) / token_video_len_proportion) / 60) * configs_service.get_config('video_token_price_v1')

def current_video_create_token_usage_v2(chapter_id):
    return 50 * configs_service.get_config('video_token_price_v2')